<?php
/**
 * 控制器基础类，实现控制器常用的方法
 * @author: yanxs <541139655@qq.com>
 * @version: 1.0
 * @date: 2021/3/8
 */

namespace App\Http\Controllers;


use App\Exceptions\CommonException;
use App\Http\Requests\BaseRequest;
use App\Repositories\PrtSysConfRepository;
use App\Services\Helper;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\View;

class BaseController extends Controller
{
    protected $sysId           = "backend"; //默认子系统为大后台
    protected $modules         = "sys";     //默认模块为系统模块
    protected $repositories    = '';        //数据仓库
    protected $systemInfo;                  //系统基础配置
    protected $exportFields    = [];        //导出excel的字段//格式 ["username" => "用户名", "mobile" => "手机"]
    protected $permissionAction= [
        "form", "save". "copy", "del", "deletes", "review", "status", "export", "import"
    ];        //定义权限操作，确定直接渲染基本操作项是否显示

    public function __construct()
    {
        app()->instance('sys_id',$this->sysId);
        app()->instance('modules',$this->modules);
    }

    /**
     * 功能首页结构view
     * @return mixed
     */
    protected function index()
    {
        return $this->view('index');
    }

    /**
     * ajax获取列表项
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    protected function table(Request $request)
    {
        $inputs = $request->all();
        $extra = [];
        if (isset($inputs['extra'])) {
            $extra = $inputs['extra'];
            unset($inputs['extra']);
        }
        $sort = '';
        if (isset($inputs['sort'])) {
            $sort = $inputs['sort'];
            unset($inputs['sort']);
        }

        $list = $this->repositories->getTableList($inputs,$sort);
        if (!empty($extra)) {
            $return = ['list' =>$list] + $extra;
        } else {
            $return = ['list' =>$list];
        }
        $htmlContents = $this->renderHtml('',$return);

        $pagesInfo = $list->toArray();

        $total = $pagesInfo['total'];

        return $this->jsonSuccess(['html' => $htmlContents,'total' => $total]);
    }
    /**
     * 通用表单展示
     * @param Request $request
     * @return mixed
     */
    protected function form(Request $request)
    {
        try {
            if($request->ajax())
            {
                $row = $this->repositories->getById($request->input('id'));
                //可额外传入的数据项
                if (!empty($request->input('extra'))) {
                    if (is_object($row)) {
                        $row = $row->toArray() + $request->input('extra');
                    }else {
                        if (empty($row)) {
                            $row = $request->input('extra');
                        } else {
                            $row = $row + $request->input('extra');
                        }
                    }
                }
                $htmlContents = $this->renderHtml($this->viewPath.'.'.$this->form, ['row' => $row]);
                return $this->jsonSuccess(['html' => $htmlContents]);
            }else{
                return view("admin.tips");
            }
        } catch (CommonException $e) {

            return $this->jsonFailed($e->getMessage());
        }

    }
    protected function detail(Request $request)
    {
        $row = $this->repositories->getById($request->input('id'));
        //可额外传入的数据项
        if (!empty($request->input('extra'))) {
            if (is_object($row)) {
                $row = $row->toArray() + $request->input('extra');
            }else {
                if (empty($row)) {
                    $row = $request->input('extra');
                } else {
                    $row = $row + $request->input('extra');
                }
            }
        }
        return $this->view("_detail",['row' => $row]);
    }

    /**
     * 普通更新，不验证表单字段
     * @param Request $request
     */
    public function update(Request $request)
    {
        $params = $request->all();
        if (empty ($params['id'])) {
            return $this->jsonFailed('更新失败');
        }
       // $res = $this->repositories->save($params);
        $where = ['id'=> $params['id']];
        unset($params['id']);
        $res = $this->repositories->update($where,$params);
        if ($res) {
            return $this->jsonSuccess([]);
        } else {
            return $this->jsonFailed('');
        }
    }

    /**
     * 数据保存(添加或更新)，适用简单情况，如果需要表
     * 单验证，请继承并覆盖
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
   /* public function save(Request $request)
    {
        $ret = $this->repositories->save($request->all());
        if ($ret) {
            return $this->jsonSuccess([]);
        } else {
            return $this->jsonFailed('');
        }
    }*/

    /**
     * 复制记录
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function copy(Request $request)
    {
        try {
            DB::beginTransaction();
            $ids = $request->input('ids');
            $list = $this->repositories->getRows(['id' =>$ids])->toArray();
            foreach ($list as $k=>$v) {
                unset($list[$k]['id'],$list[$k]['status'],$list[$k]['check_status'],$list[$k]['updated_at'],$list[$k]['deleted_at']);
                $list[$k]['created_at'] = time();
                $list[$k]['updated_at'] = time();
            }
            try {
                $this->repositories->batchInsert('',$list);
            } catch (\Exception $e) {
                return $this->jsonFailed('复制出错');
                DB::rollBack();
            }
            DB::commit();
            return $this->jsonSuccess(['']);
        }catch (CommonException $e) {
            DB::rollBack();
            return $this->jsonFailed($e->getMessage());
        }
    }
    /**
     * 删除记录(软删除)
     * @param Request $request
     * @return bool
     */
    protected function delete(Request $request)
    {
        $ret = $this->repositories->delete($request->id);
        if($ret) {
            return $this->jsonSuccess(['']);
        } else {
            return $this->jsonFailed( "删除记录失败");
        }
    }

    /**
     * 删除多条记录(软删除)
     * @param Request $request
     * @return bool
     */
    protected function batchDelete(Request $request)
    {
        $ids = $request->input('ids');
        if (empty($ids)) {
            return $this->jsonFailed( "错误的参数!");
        }
        foreach ($ids as $k=>$id) {
            $ret = $this->repositories->delete($id);
        }
        return $this->jsonSuccess([]);
    }


    /**
     * 审核/反审核
     * @param Request $request
     */
    protected function review(Request  $request)
    {
        $ids = $request->input('ids');
        $status = $request->input('where');
        $where['id']   = $ids;
        $data['check_status'] = $status;
        $res = $this->repositories->updateWhere($where,$data);
        return $this->jsonSuccess([]);
    }

    /**
     * 导出数据表格
     * @param Request $request
     */
    protected function export(Request  $request)
    {
        $params = $request->data;

        if ($params == "temp") {
            $collectList = $this->repositories->getRows([],"id","asc",1);
            $exportName = "导入报表模板";
        } else {
            $where = json_decode($params,true);
            $collectList = $this->repositories->getList($where);
            $exportName = "报表导出-".date("Y-m-d");
        }

        //将列表状态标识字段转化为实体数据
        $collectList = $this->repositories->transFlagToEntity($collectList->toArray());
        //走实时还是队列
        if (config("common.report_down_type") == "sync") {

            $exportFields = [];
            if (!empty($this->exportFields)) { //定义了导出表的格式
                $exportFields = $this->exportFields;
            } else { //未定义的情况下导全部字段
                $tableInfo = $this->repositories->getTableStruct();
                foreach ($tableInfo as $k => $v) { //直接解析数据库字段及注释
                    $comment = '';
                    if (empty( $v['Comment'])) {
                        $comment = $v['Field'];
                    } elseif(preg_match('/\[(.*)\]/',$v['Comment'],$res)) {
                        $comment = $res[1];
                    } else {
                        $comment = $v['Comment'];
                    }
                    if ($params == "temp") {  //导出模板的情况下去掉一些字段
                        $noDisplayField = ["id", "sys_code", "updated_at", "deleted_at", "creator_uid", "status","check_status","updater_uid", "created_at"];
                        if (in_array($v['Field'], $noDisplayField)) {
                            continue;
                        }
                    }
                    $exportFields[$v['Field']] = $comment;
                }
            }
            //执行导出操作
            Helper::exportExcel($exportName,$collectList,$exportFields);

        } else {
            //走队列,长io事件，用mysql做辅助队列
        }
    }

    /**
     * 数据导入
     * @param Request $request
     */
    protected function import(Request $request)
    {
        try {
            if (is_uploaded_file($_FILES['file']['tmp_name'])) {
                $filename = $_FILES['file']['name'];
                //解析excel数据
                $parseData = Helper::parseExcel($filename,$_FILES['file']['tmp_name']);

                //组织返回数据
                $newData = [];
                foreach ($parseData['data'] as $k=>$v) {
                    foreach ($v as $kk=>$vv) {
                        if (!empty($parseData['head'][$kk])) {
                            $newData[$k][$parseData['head'][$kk]] = $parseData['data'][$k][$kk];
                        }
                    }
                }

                $tableInfo = $this->repositories->getTableStruct();
                foreach ($tableInfo as $k => $v) { //直接解析数据库字段及注释
                    $comment = '';
                    if (empty( $v['Comment'])) {
                        $comment = $v['Field'];
                    } elseif(preg_match('/\[(.*)\]/',$v['Comment'],$res)) {
                        $comment = $res[1];
                    } else {
                        $comment = $v['Comment'];
                    }
                    $exportFields[$v['Field']] = $comment;
                }
                //交换表字段注释的键和值
                $trans = array_flip($exportFields);
                $total = 0;
                foreach ($newData as $k=>$v) {

                    $insertData = [];
                    foreach ($v as $kk=>$vv) {
                        if (isset($trans[$kk])) {
                            $insertData[$trans[$kk]] = $vv;
                        }
                    }
                    if (isset($insertData['id'])) {
                        unset($insertData['id']);
                    }
                    unset($insertData['deleted_at']);
                    unset($insertData['updated_at']);
                    unset($insertData['created_at']);
                    if (!empty($insertData)) {
                        $insertData = $this->repositories->unTransFlagToEntity($insertData);
                        $insertData['created_at'] = time();
                        $this->repositories->save($insertData);
                        $total++;
                    }
                }
                return $this->jsonSuccess("已成功导入".$total."条数据!");
            } else {
                return $this->jsonFailed( "上传文件出错");
            }
        } catch (CommonException $e) {
            return $this->jsonFailed( $e->getMessage());
        }
    }

    /**
     * 状态操作
     * @param Request $request
     */
    protected function status(Request  $request)
    {
        $ids = $request->input('ids');
        $status = $request->input('where');
        $where['id']   = $ids;
        $data['status'] = $status;
        $res = $this->repositories->updateWhere($where,$data);
        return $this->jsonSuccess([]);

    }

    /**
     *视图渲染
     * @param $path view的具体文件
     * @return mixed
     */
    protected function view($path, $data = [])
    {
        return \view($this->viewPath.'.'.$path, $data);
    }
    /**
     * 成功提示
     * @param $tpl 模板名称
     * @param array $data 传入视图的变量
     * @return string html字符串
     */
    public function tipsSuccess(Request $request)
    {
        $tpl = $this->tipSuccessTpl;
        $post = $request->post();
        $text = $post['text']?$post['text']:null;
        $interval = $post['interval']?$post['interval']:1;
        $title = $post['title']?$post['title']:null;


        $data = [
            "html" => $text,
            "interval" => $interval,
            "title"  => $title,
        ];

        $content = $this->renderHtml($tpl,['data' =>$data]);
        return response()->json(['status' => 200, 'html' => $content]);


    }
    /**
     * 删除记录提示
     * @param $tpl 模板名称
     * @param array $data 传入视图的变量
     * @return string html字符串
     */
    public function tipsWarn(Request $request)
    {
        $tpl = $this->tipWarnTpl;
        $post = $request->post();
        $text = $post['text']?$post['text']:null;
        $url = $post['url']?$post['url']:null;
        $title = $post['title']?$post['title']:null;
        $recover = $post['recover']?$post['recover']:"0";
        $isCallback = $post['is_callback']?$post['is_callback']:"0";
        $isComfirm = $post['is_comfirm']?$post['is_comfirm']:"1";

        $data = [
            "html" => $text,
            "url"  => $url,
            "title"  => $title,
            "recover"  => $recover,
            "is_callback"  => $isCallback,
            "is_comfirm"  => $isComfirm,
        ];

        $content = $this->renderHtml($tpl,['data' =>$data]);
        return response()->json(['status' => 200, 'html' => $content]);


    }

    /**
     * 直接把视图转化为html返回
     * @param $tpl 模板名称
     * @param array $data 传入视图的变量
     * @return string html字符串
     */
    protected function renderHtml($tpl,$data = [])
    {
        if (empty($tpl)) {
            $tpl = $this->viewPath.'.'.$this->tableTpl;
        }
        return View::make($tpl,$data)->render();
    }
    /**
     * 返回成功的标准json格式
     * @param $data
     * @return \Illuminate\Http\JsonResponse
     */
    public function jsonSuccess($data)
    {
        return response()->json(['status' => 200, 'success' => 'true', 'data' => $data]);
    }

    /**
     * 返回失败的标准json格式
     * @param $errCode
     * @param $errMsg
     * @return \Illuminate\Http\JsonResponse
     */
    public function jsonFailed( $errMsg,$errCode="404")
    {
        return response()->json(['status' => 404 ,'success' => 'false','err_code'=>$errCode, 'err_msg' => $errMsg,'message' =>$errMsg]);
    }

    /**
     * 获取系统配置
     * @return array
     */
    protected function getSysSetting()
    {
        $setting = app(PrtSysConfRepository::class)->getOrderByRow(['status' => PUBLIC_YES],"sort DESC")->toArray();
        $pageList = explode(',',$setting['page_list']);

        return [
            'default_pages_limit' => $setting['page_limit'] ?? config("common.default_page_limit"),
            'paginate_type'       => 'number', //number 带数字的 normal 普通的
            'page_lists'           => $pageList
        ] + $setting;
    }
}
